/*
 * Copyright (C) 2011, EADS France
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */
package xowl.gmi.controller;

/**
 *
 * @author Laurent WOUTERS
 */
public class CommandFactory {
    private static final String meta = "http://www.xowl.org/gmi/model/meta#";
    private static final String command = "http://www.xowl.org/gmi/model/command#";
    
    private int counter;
    private xowl.utils.logging.Logger log;
    private xowl.interpreter.Repository repository;
    private xowl.lang.owl2.Ontology ontoCommand;
    private xowl.interpreter.Transformer transformer;
    
    private xowl.lang.runtime.Entity commandCreate;
    private xowl.lang.runtime.Entity commandDelete;
    private xowl.lang.runtime.Entity commandAttach;
    private xowl.lang.runtime.Entity commandDetach;
    private xowl.lang.runtime.Entity commandOrder;
    private xowl.lang.runtime.Entity commandUnorder;
    private xowl.lang.runtime.Entity commandSet;
    private xowl.lang.runtime.Entity commandUnset;
    private xowl.lang.runtime.Entity commandConnect;
    private xowl.lang.runtime.Entity commandDisconnect;
    private xowl.lang.runtime.Entity commandSymbol;
    private xowl.lang.runtime.Entity commandParent;
    private xowl.lang.runtime.Entity commandChild;
    private xowl.lang.runtime.Entity commandConnector;
    private xowl.lang.runtime.Entity commandNode;
    private xowl.lang.runtime.Entity commandFrom;
    private xowl.lang.runtime.Entity commandTo;
    private xowl.lang.runtime.Entity commandIndex;
    private xowl.lang.runtime.Entity metaTrace;
    private xowl.lang.runtime.Entity metaConnector;
    private xowl.lang.runtime.Entity metaProperty;
    private xowl.lang.runtime.Entity metaOrigin;
    private xowl.lang.runtime.Entity metaTarget;
    
    public xowl.lang.runtime.Entity getMetaTrace() { return metaTrace; }
    public xowl.lang.runtime.Entity getMetaConnector() { return metaConnector; }
    public xowl.lang.runtime.Entity getMetaProperty() { return metaProperty; }
    public xowl.lang.runtime.Entity getMetaOrigin() { return metaOrigin; }
    public xowl.lang.runtime.Entity getMetaTarget() { return metaTarget; }
    
    public CommandFactory(xowl.utils.logging.Logger log, xowl.interpreter.Repository repository, xowl.lang.owl2.Ontology ontoCommand, xowl.interpreter.Transformer transformer) {
        this.counter = 0;
        this.log = log;
        this.repository = repository;
        this.ontoCommand = ontoCommand;
        this.transformer = transformer;
        
        this.commandCreate = repository.resolveEntity(command + "create");
        this.commandDelete = repository.resolveEntity(command + "delete");
        this.commandAttach = repository.resolveEntity(command + "Attach");
        this.commandDetach = repository.resolveEntity(command + "Detach");
        this.commandOrder = repository.resolveEntity(command + "Order");
        this.commandUnorder = repository.resolveEntity(command + "Unorder");
        this.commandSet = repository.resolveEntity(command + "set");
        this.commandUnset = repository.resolveEntity(command + "unset");
        this.commandConnect = repository.resolveEntity(command + "Connect");
        this.commandDisconnect = repository.resolveEntity(command + "Disconnect");
        this.commandSymbol = repository.resolveEntity(command + "symbol");
        this.commandParent = repository.resolveEntity(command + "parent");
        this.commandChild = repository.resolveEntity(command + "child");
        this.commandConnector = repository.resolveEntity(command + "connector");
        this.commandNode = repository.resolveEntity(command + "node");
        this.commandFrom = repository.resolveEntity(command + "from");
        this.commandTo = repository.resolveEntity(command + "to");
        this.commandIndex = repository.resolveEntity(command + "index");
        this.metaTrace = repository.resolveEntity(meta + "trace");
        this.metaConnector = repository.resolveEntity(meta + "connector");
        this.metaProperty = repository.resolveEntity(meta + "property");
        this.metaOrigin = repository.resolveEntity(meta + "origin");
        this.metaTarget = repository.resolveEntity(meta + "target");
    }
    
    private int getNextNumber() {
        int temp = counter;
        counter++;
        return temp;
    }
    
    public Command create(xowl.lang.owl2.IRI node, xowl.lang.owl2.IRI symbol) {
        xowl.lang.owl2.ObjectPropertyAssertion axiom = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom.setObjectProperty(commandCreate.getHasIRI());
        axiom.setIndividual(node);
        axiom.setValueIndividual(symbol);
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom, true));
        return new Command("CommandCreate" + Integer.toString(getNextNumber()), log, repository, transformer, changeset);
    }
    
    public Command delete(xowl.lang.owl2.IRI node, xowl.lang.owl2.IRI symbol) {
        xowl.lang.owl2.ObjectPropertyAssertion axiom = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom.setObjectProperty(commandDelete.getHasIRI());
        axiom.setIndividual(node);
        axiom.setValueIndividual(symbol);
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom, true));
        return new Command("CommandDelete" + Integer.toString(getNextNumber()), log, repository, transformer, changeset);
    }
    
    public Command attach(xowl.lang.owl2.IRI symbol, xowl.lang.owl2.IRI parent, xowl.lang.owl2.IRI child) {
        String name = "CommandAttach" + Integer.toString(getNextNumber());
        xowl.lang.owl2.IRI comm = repository.getIRI(command + name);
        xowl.lang.owl2.ClassAssertion axiom1 = new xowl.lang.owl2.ClassAssertion();
        axiom1.setClasse(commandAttach.getHasIRI());
        axiom1.setIndividual(comm);
        xowl.lang.owl2.ObjectPropertyAssertion axiom2 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom2.setObjectProperty(commandSymbol.getHasIRI());
        axiom2.setIndividual(comm);
        axiom2.setValueIndividual(symbol);
        xowl.lang.owl2.ObjectPropertyAssertion axiom3 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom3.setObjectProperty(commandParent.getHasIRI());
        axiom3.setIndividual(comm);
        axiom3.setValueIndividual(parent);
        xowl.lang.owl2.ObjectPropertyAssertion axiom4 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom4.setObjectProperty(commandChild.getHasIRI());
        axiom4.setIndividual(comm);
        axiom4.setValueIndividual(child);
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom1, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom2, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom3, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom4, true));
        return new Command(name, log, repository, transformer, changeset);
    }
    
    public Command detach(xowl.lang.owl2.IRI symbol, xowl.lang.owl2.IRI parent, xowl.lang.owl2.IRI child) {
        String name = "CommandDetach" + Integer.toString(getNextNumber());
        xowl.lang.owl2.IRI comm = repository.getIRI(command + name);
        xowl.lang.owl2.ClassAssertion axiom1 = new xowl.lang.owl2.ClassAssertion();
        axiom1.setClasse(commandDetach.getHasIRI());
        axiom1.setIndividual(comm);
        xowl.lang.owl2.ObjectPropertyAssertion axiom2 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom2.setObjectProperty(commandSymbol.getHasIRI());
        axiom2.setIndividual(comm);
        axiom2.setValueIndividual(symbol);
        xowl.lang.owl2.ObjectPropertyAssertion axiom3 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom3.setObjectProperty(commandParent.getHasIRI());
        axiom3.setIndividual(comm);
        axiom3.setValueIndividual(parent);
        xowl.lang.owl2.ObjectPropertyAssertion axiom4 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom4.setObjectProperty(commandChild.getHasIRI());
        axiom4.setIndividual(comm);
        axiom4.setValueIndividual(child);
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom1, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom2, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom3, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom4, true));
        return new Command(name, log, repository, transformer, changeset);
    }
    
    public Command order(xowl.lang.owl2.IRI symbol, xowl.lang.owl2.IRI parent, xowl.lang.owl2.IRI child, int index) {
        String name = "CommandOrder" + Integer.toString(getNextNumber());
        xowl.lang.owl2.IRI comm = repository.getIRI(command + name);
        xowl.lang.owl2.ClassAssertion axiom1 = new xowl.lang.owl2.ClassAssertion();
        axiom1.setClasse(commandOrder.getHasIRI());
        axiom1.setIndividual(comm);
        xowl.lang.owl2.ObjectPropertyAssertion axiom2 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom2.setObjectProperty(commandSymbol.getHasIRI());
        axiom2.setIndividual(comm);
        axiom2.setValueIndividual(symbol);
        xowl.lang.owl2.ObjectPropertyAssertion axiom3 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom3.setObjectProperty(commandParent.getHasIRI());
        axiom3.setIndividual(comm);
        axiom3.setValueIndividual(parent);
        xowl.lang.owl2.ObjectPropertyAssertion axiom4 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom4.setObjectProperty(commandChild.getHasIRI());
        axiom4.setIndividual(comm);
        axiom4.setValueIndividual(child);
        xowl.lang.owl2.DataPropertyAssertion axiom5 = new xowl.lang.owl2.DataPropertyAssertion();
        axiom5.setDataProperty(commandIndex.getHasIRI());
        axiom5.setIndividual(comm);
        axiom5.setValueLiteral(getLiteral(index));
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom1, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom2, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom3, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom4, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom5, true));
        return new Command(name, log, repository, transformer, changeset);
    }
    
    public Command unorder(xowl.lang.owl2.IRI symbol, xowl.lang.owl2.IRI parent, xowl.lang.owl2.IRI child, int index) {
        String name = "CommandUnorder" + Integer.toString(getNextNumber());
        xowl.lang.owl2.IRI comm = repository.getIRI(command + name);
        xowl.lang.owl2.ClassAssertion axiom1 = new xowl.lang.owl2.ClassAssertion();
        axiom1.setClasse(commandUnorder.getHasIRI());
        axiom1.setIndividual(comm);
        xowl.lang.owl2.ObjectPropertyAssertion axiom2 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom2.setObjectProperty(commandSymbol.getHasIRI());
        axiom2.setIndividual(comm);
        axiom2.setValueIndividual(symbol);
        xowl.lang.owl2.ObjectPropertyAssertion axiom3 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom3.setObjectProperty(commandParent.getHasIRI());
        axiom3.setIndividual(comm);
        axiom3.setValueIndividual(parent);
        xowl.lang.owl2.ObjectPropertyAssertion axiom4 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom4.setObjectProperty(commandChild.getHasIRI());
        axiom4.setIndividual(comm);
        axiom4.setValueIndividual(child);
        xowl.lang.owl2.DataPropertyAssertion axiom5 = new xowl.lang.owl2.DataPropertyAssertion();
        axiom5.setDataProperty(commandIndex.getHasIRI());
        axiom5.setIndividual(comm);
        axiom5.setValueLiteral(getLiteral(index));
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom1, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom2, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom3, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom4, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom5, true));
        return new Command(name, log, repository, transformer, changeset);
    }
    
    public Command set(xowl.lang.owl2.IRI node, Object value) {
        xowl.lang.owl2.DataPropertyAssertion axiom = new xowl.lang.owl2.DataPropertyAssertion();
        axiom.setDataProperty(commandSet.getHasIRI());
        axiom.setIndividual(node);
        axiom.setValueLiteral(getLiteral(value));
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom, true));
        return new Command("CommandSet" + Integer.toString(getNextNumber()), log, repository, transformer, changeset);
    }
    
    public Command unset(xowl.lang.owl2.IRI node, Object value) {
        xowl.lang.owl2.DataPropertyAssertion axiom = new xowl.lang.owl2.DataPropertyAssertion();
        axiom.setDataProperty(commandUnset.getHasIRI());
        axiom.setIndividual(node);
        axiom.setValueLiteral(getLiteral(value));
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom, true));
        return new Command("CommandUnset" + Integer.toString(getNextNumber()), log, repository, transformer, changeset);
    }
    
    public Command connect(xowl.lang.owl2.IRI connector, xowl.lang.owl2.IRI node, xowl.lang.owl2.IRI left, xowl.lang.owl2.IRI right) {
        String name = "CommandConnect" + Integer.toString(getNextNumber());
        xowl.lang.owl2.IRI comm = repository.getIRI(command + name);
        xowl.lang.owl2.ClassAssertion axiom1 = new xowl.lang.owl2.ClassAssertion();
        axiom1.setClasse(commandConnect.getHasIRI());
        axiom1.setIndividual(comm);
        xowl.lang.owl2.ObjectPropertyAssertion axiom2 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom2.setObjectProperty(commandNode.getHasIRI());
        axiom2.setIndividual(comm);
        axiom2.setValueIndividual(node);
        xowl.lang.owl2.ObjectPropertyAssertion axiom3 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom3.setObjectProperty(commandConnector.getHasIRI());
        axiom3.setIndividual(comm);
        axiom3.setValueIndividual(connector);
        xowl.lang.owl2.ObjectPropertyAssertion axiom4 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom4.setObjectProperty(commandFrom.getHasIRI());
        axiom4.setIndividual(comm);
        axiom4.setValueIndividual(left);
        xowl.lang.owl2.ObjectPropertyAssertion axiom5 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom5.setObjectProperty(commandTo.getHasIRI());
        axiom5.setIndividual(comm);
        axiom5.setValueIndividual(right);
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom1, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom2, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom3, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom4, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom5, true));
        return new Command(name, log, repository, transformer, changeset);
    }
    
    public Command disconnect(xowl.lang.owl2.IRI connector, xowl.lang.owl2.IRI node, xowl.lang.owl2.IRI left, xowl.lang.owl2.IRI right) {
        String name = "CommandDisconnect" + Integer.toString(getNextNumber());
        xowl.lang.owl2.IRI comm = repository.getIRI(command + name);
        xowl.lang.owl2.ClassAssertion axiom1 = new xowl.lang.owl2.ClassAssertion();
        axiom1.setClasse(commandDisconnect.getHasIRI());
        axiom1.setIndividual(comm);
        xowl.lang.owl2.ObjectPropertyAssertion axiom2 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom2.setObjectProperty(commandNode.getHasIRI());
        axiom2.setIndividual(comm);
        axiom2.setValueIndividual(node);
        xowl.lang.owl2.ObjectPropertyAssertion axiom3 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom3.setObjectProperty(commandConnector.getHasIRI());
        axiom3.setIndividual(comm);
        axiom3.setValueIndividual(connector);
        xowl.lang.owl2.ObjectPropertyAssertion axiom4 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom4.setObjectProperty(commandFrom.getHasIRI());
        axiom4.setIndividual(comm);
        axiom4.setValueIndividual(left);
        xowl.lang.owl2.ObjectPropertyAssertion axiom5 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom5.setObjectProperty(commandTo.getHasIRI());
        axiom5.setIndividual(comm);
        axiom5.setValueIndividual(right);
        xowl.interpreter.Changeset changeset = new xowl.interpreter.Changeset();
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom1, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom2, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom3, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom4, true));
        changeset.add(new xowl.interpreter.Change(ontoCommand, axiom5, true));
        return new Command(name, log, repository, transformer, changeset);
    }
    
    private xowl.lang.owl2.Literal getLiteral(Object v) {
        xowl.lang.owl2.Literal lit = new xowl.lang.owl2.Literal();
        xowl.lang.runtime.Literal temp = (xowl.lang.runtime.Literal)repository.getLiteral(v);
        lit.setLexicalValue(temp.getLexicalValue());
        lit.setMemberOf(temp.getMemberOf().getInterpretationOf().getHasIRI());
        return lit;
    }
}
